package com.kmxd.ams.app.archive;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kmxd.ams.client.archive.IArchiveRuleFieldSvc;
import com.kmxd.ams.client.archive.dto.ArchiveRuleFieldAddDTO;
import com.kmxd.ams.client.archive.dto.ArchiveRuleFieldEditDTO;
import com.kmxd.ams.client.archive.dto.ArchiveRuleFieldQueryDTO;
import com.kmxd.ams.client.archive.vo.ArchiveRuleFieldListVO;
import com.kmxd.ams.client.archive.vo.ArchiveRuleFieldVO;
import com.kmxd.ams.core.common.constant.ArchConst;
import com.kmxd.ams.core.common.constant.CacheConst;
import com.kmxd.ams.core.common.constant.ErrorCode;
import com.kmxd.ams.core.common.enums.RuleFieldTypeEnum;
import com.kmxd.ams.core.common.query.QueryGen;
import com.kmxd.ams.core.exception.BizTipException;
import com.kmxd.ams.core.util.IdUtil;
import com.kmxd.ams.infra.archive.entity.ArchiveRuleField;
import com.kmxd.ams.infra.archive.mapper.ArchiveRuleFieldMapper;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import org.apache.commons.compress.utils.Lists;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 整理规则-规则字段 服务实现类
 *
 * @author nickbi
 * @since 2022-07-30
 */
@Service
@AllArgsConstructor
@CacheConfig(cacheNames = CacheConst.CACHE_PREFIX_ARCHIVE_RULE_FIELD)
public class ArchiveRuleFieldSvcImpl extends ServiceImpl<ArchiveRuleFieldMapper, ArchiveRuleField>
    implements IArchiveRuleFieldSvc {

  private ArchiveRuleFieldMapper archiveRuleFieldMapper;

  @Cacheable(keyGenerator = "myKeyGenerator")
  @Override
  public Page<ArchiveRuleFieldListVO> selectPage(Page reqPage, ArchiveRuleFieldQueryDTO req) {
    LambdaQueryWrapper<ArchiveRuleField> queryWrapper =
        QueryGen.init(new QueryWrapper<ArchiveRuleField>(), req).lambda();
    queryWrapper.orderByAsc(ArchiveRuleField::getSort);
    Page<ArchiveRuleField> page = archiveRuleFieldMapper.selectPage(reqPage, queryWrapper);
    Page<ArchiveRuleFieldListVO> voPage = BeanUtil.copyProperties(page, Page.class);
    voPage.setRecords(BeanUtil.copyToList(page.getRecords(), ArchiveRuleFieldListVO.class));
    return voPage;
  }

  @Cacheable(keyGenerator = "myKeyGenerator")
  @Override
  public List<ArchiveRuleFieldListVO> selectList(ArchiveRuleFieldQueryDTO req) {
    LambdaQueryWrapper<ArchiveRuleField> queryWrapper =
        QueryGen.init(new QueryWrapper<ArchiveRuleField>(), req).lambda();
    queryWrapper.orderByAsc(ArchiveRuleField::getSort);
    List<ArchiveRuleField> list = archiveRuleFieldMapper.selectList(queryWrapper);
    return BeanUtil.copyToList(list, ArchiveRuleFieldListVO.class);
  }

  @Caching(
      evict = {
        @CacheEvict(allEntries = true),
        @CacheEvict(cacheNames = CacheConst.CACHE_PREFIX_ARCHIVE_RULE_MAIN, allEntries = true)
      })
  @Override
  @Transactional(rollbackFor = Exception.class)
  public void add(ArchiveRuleFieldAddDTO req) {
    ArchiveRuleField entity = BeanUtil.copyProperties(req, ArchiveRuleField.class);
    if (entity.getFieldCode().contains(ArchConst.SEQUENSE)) {
      entity.setEnableIncrement(Boolean.FALSE);
      entity.setEnableGroup(Boolean.FALSE);
    }
    if (entity.getType().equals(RuleFieldTypeEnum.FIXED.getCode())) {
      entity.setEnableIncrement(Boolean.FALSE);
      entity.setEnableGroup(Boolean.FALSE);
    } else {
      entity.setEnableGroup(Boolean.TRUE);
    }
    archiveRuleFieldMapper.insert(entity);
  }

  @Caching(
      evict = {
        @CacheEvict(allEntries = true),
        @CacheEvict(cacheNames = CacheConst.CACHE_PREFIX_ARCHIVE_RULE_MAIN, allEntries = true)
      })
  @Override
  @Transactional(rollbackFor = Exception.class)
  public void edit(ArchiveRuleFieldEditDTO req) {
    ArchiveRuleField entity = BeanUtil.copyProperties(req, ArchiveRuleField.class);
    if (entity.getFieldCode().contains(ArchConst.SEQUENSE)) {
      entity.setEnableIncrement(Boolean.FALSE);
      entity.setEnableGroup(Boolean.FALSE);
    }
    if (entity.getType().equals(RuleFieldTypeEnum.FIXED.getCode())) {
      entity.setEnableIncrement(Boolean.FALSE);
      entity.setEnableGroup(Boolean.FALSE);
    }
    archiveRuleFieldMapper.updateById(entity);
  }

  @Caching(
      evict = {
        @CacheEvict(allEntries = true),
        @CacheEvict(cacheNames = CacheConst.CACHE_PREFIX_ARCHIVE_RULE_MAIN, allEntries = true)
      })
  @Override
  @Transactional(rollbackFor = Exception.class)
  public void remove(String ids) {
    Set<Long> idList = IdUtil.split(ids);
    this.baseMapper.deleteBatchIds(idList);
  }

  @Cacheable(keyGenerator = "myKeyGenerator")
  @Override
  public ArchiveRuleFieldVO view(Long id) {
    ArchiveRuleField entity = archiveRuleFieldMapper.selectById(id);
    return BeanUtil.copyProperties(entity, ArchiveRuleFieldVO.class);
  }

  @Transactional(rollbackFor = Exception.class)
  @Caching(
      evict = {
        @CacheEvict(allEntries = true),
        @CacheEvict(cacheNames = CacheConst.CACHE_PREFIX_ARCHIVE_RULE_MAIN, allEntries = true)
      })
  @Override
  public void changeSort(String ids) {
    if (CharSequenceUtil.isBlank(ids)) {
      throw BizTipException.instance(ErrorCode.VALIDATE_NOT_NULL, "排序id不能为空");
    }
    List<Long> idList = IdUtil.splitSortList(ids);
    if (ObjectUtil.isEmpty(idList)) {
      throw BizTipException.instance(ErrorCode.VALIDATE_NOT_NULL, "排序id不能为空");
    }
    List<ArchiveRuleField> archiveRuleFields = listByIds(idList);
    if (ObjectUtil.isEmpty(archiveRuleFields)) {
      return;
    }
    Map<Long, ArchiveRuleField> map =
        archiveRuleFields.stream()
            .collect(Collectors.toMap(ArchiveRuleField::getId, Function.identity()));
    List<ArchiveRuleField> newSortList = Lists.newArrayList();
    for (int i = 0; i < idList.size(); i++) {
      Long id = idList.get(i);
      ArchiveRuleField field = map.get(id);
      if (ObjectUtil.isNull(field)) {
        // 跳出，进行下个字段设置
        break;
      }
      field.setSort(i + 1);
      newSortList.add(field);
    }
    if (ObjectUtil.isEmpty(newSortList)) {
      return;
    }
    updateBatchById(newSortList);
  }
}
